<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>4.2-响应式数据的基本实现</title>
</head>

<body>
    <div id="container"></div>
</body>
<script>
    /**
     * 两点线索
     * - 当副作用函数 effect 执行时，会触发字段 obj.text 的读取操作
     * - 当修改 obj.text 的值时，会触发字段 obj.text 的设置操作
     * 
     * 在 ES2015 之前，只能通过 Object.defineProperty 函数实现，这也是 Vue.js 2 所采用的方式
     * 在 ES2015+ 中，我们可以使用代理对象Proxy 来实现，这也是 Vue.js 3 所采用的方式
     * 
     * 只需要理解响应式数据的基本实现和工作原理即可
     * */ 

    // 存储副作用函数的桶
    const bucket = new Set()
    // 原始数据
    const data = { text: 'hello world' }
    // 对原始数据的代理
    const obj = new Proxy(data, {
        // 拦截读取操作
        get(target, key) {
            // 将副作用函数 effect 添加到存储副作用函数的桶中
            bucket.add(effect)
            // 返回属性值
            return target[key]
        },
        // 拦截设置操作
        set(target, key, newVal) {
            // 设置属性值
            target[key] = newVal
            // 把副作用函数从桶里取出并执行
            bucket.forEach(fn => fn())
            // 返回 true 代表设置操作成功
            return true
        }
    })

    // 副作用函数
    function effect() {
        document.body.innerText = obj.text
    }
    // 执行副作用函数，触发读取
    effect()
    // 1 秒后修改响应式数据
    setTimeout(() => {
        obj.text = 'hello vue3'
    }, 1000)
</script>

</html>